{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "# 将所有特征串联起来，构成RS_Train.csv\n",
    "# RS_Test.csv\n",
    "# 为最后推荐系统做准备\n",
    "from __future__ import division\n",
    "\n",
    "import cPickle\n",
    "import numpy as np\n",
    "import scipy.io as sio\n",
    "import scipy.sparse as ss\n",
    "from numpy.random import random\n",
    "from collections import defaultdict\n",
    "import math\n",
    "\n",
    "class RecommonderSystem:\n",
    "    def __init__(self):\n",
    "        # 读入数据做初始化\n",
    "\n",
    "        # 用户和活动新的索引\n",
    "        self.userIndex = cPickle.load(open(\"PE_userIndex.pkl\", 'rb'))\n",
    "        self.eventIndex = cPickle.load(open(\"PE_eventIndex.pkl\", 'rb'))\n",
    "        self.n_users = len(self.userIndex)\n",
    "        self.n_items = len(self.eventIndex)\n",
    "\n",
    "        # 用户-活动关系矩阵R\n",
    "        # 在train_SVD会重新从文件中读取,二者要求的格式不同，来不及统一了:(\n",
    "        self.userEventScores = sio.mmread(\"PE_userEventScores\").todense()\n",
    "\n",
    "        # 倒排表\n",
    "        ##每个用户参加的事件\n",
    "        self.itemsForUser = cPickle.load(open(\"PE_eventsForUser.pkl\", 'rb'))\n",
    "        ##事件参加的用户\n",
    "        self.usersForItem = cPickle.load(open(\"PE_usersForEvent.pkl\", 'rb'))\n",
    "        # 基于模型的协同过滤参数初始化,训练\n",
    "        self.init_SVD()\n",
    "        self.train_SVD()\n",
    "\n",
    "        # 根据用户属性计算出的用户之间的相似度\n",
    "        self.userSimMatrix = sio.mmread(\"US_userSimMatrix\").todense()\n",
    "\n",
    "        # 根据活动属性计算出的活动之间的相似度\n",
    "        self.eventPropSim = sio.mmread(\"EV_eventPropSim\").todense()\n",
    "        self.eventContSim = sio.mmread(\"EV_eventContSim\").todense()\n",
    "\n",
    "        # 每个用户的朋友的数目\n",
    "        self.numFriends = sio.mmread(\"UF_numFriends\")\n",
    "        # 用户的每个朋友参加活动的分数对该用户的影响\n",
    "        self.userFriends = sio.mmread(\"UF_userFriends\").todense()\n",
    "\n",
    "        # 活动本身的热度\n",
    "        self.eventPopularity = sio.mmread(\"EA_eventPopularity\").todense()\n",
    "        for u in range(0,self.n_users):\n",
    "            if len(self.itemsForUser[u])>0:\n",
    "                self.useraverscore[u]=self.R[u,:].sum()/len(self.itemsForUser[u])\n",
    "            else:\n",
    "                self.useraverscore[u]=0;\n",
    "                \n",
    "        for i in range(0,self.n_items):\n",
    "            if len(self.usersForItem[i])>0:\n",
    "                self.itemaverscore[i]=self.R[:,i].sum()/len(self.usersForItem[i])\n",
    "                \n",
    "            else:\n",
    "                self.itemaverscore[i]=0;\n",
    "                                                                       \n",
    "        for u1 in range(0,self.n_users):\n",
    "            for u2 in range(u1,self.n_users):\n",
    "                self.usersimularity[u1,u2]=self.sim_cal_UserCF( u1, u2,self.useraverscore[u1],self.useraverscore[u2]);\n",
    "                self.usersimularity[u2,u1]=self.usersimularity[u1,u2];\n",
    "        \n",
    "        for i1 in range(0,self.n_items):\n",
    "            for i2 in range(i1,self.n_items):\n",
    "                self.itemsimularity[i1,i2]=self.sim_cal_ItemCF( i1, i2,self.itemaverscore[i1],self.itemaverscore[i2]);\n",
    "                self.itemsimularity[i2,i1]=self.itemsimularity[i1,i2];\n",
    "    def init_SVD(self, K=20):\n",
    "        # 初始化模型参数（for 基于模型的协同过滤SVD_CF）\n",
    "        self.K = K\n",
    "        self.useraverscore=np.zeros(self.n_users)\n",
    "        self.itemaverscore=np.zeros(self.n_items)\n",
    "        self.usersimularity= np.zeros((self.n_users,self.n_users))\n",
    "        self.itemsimularity= np.zeros((self.n_items,self.n_items))\n",
    "        # init parameters\n",
    "        # bias\n",
    "        \n",
    "        self.bi = np.zeros(self.n_items)\n",
    "        self.bu = np.zeros(self.n_users)\n",
    "        # the small matrix\n",
    "        self.P = random((self.n_users, self.K)) / 20 * (np.sqrt(self.K))  #设小一点好收敛\n",
    "        self.Q = random((self.K, self.n_items)) / 20 * (np.sqrt(self.K)) #设小一点好收敛\n",
    "\n",
    "    def train_SVD(self, trainfile='train.csv', steps=100, gamma=0.04, Lambda=0.15):\n",
    "        # 训练SVD模型（for 基于模型的协同过滤SVD_CF）\n",
    "        # gamma：为学习率\n",
    "        # Lambda：正则参数\n",
    "\n",
    "        # 偷懒了，为了和原来的代码的输入接口一样，直接从训练文件中去读取数据\n",
    "        print \"SVD Train...\"\n",
    "        ftrain = open(trainfile, 'r')\n",
    "        ftrain.readline()\n",
    "        self.mu = 0.0\n",
    "        n_records = 0\n",
    "        uids = []  # 每条记录的用户索引\n",
    "        i_ids = []  # 每条记录的item索引\n",
    "        # 用户-Item关系矩阵R（内容同userEventScores相同），临时变量，训练完了R不再需要\n",
    "        R = np.zeros((self.n_users, self.n_items))\n",
    "        Event_Attendence=np.zeros(self.n_items);\n",
    "        User_Attendence=np.zeros(self.n_users);\n",
    "        for line in ftrain:\n",
    "            cols = line.strip().split(\",\")\n",
    "            u = self.userIndex[cols[0]]  # 用户\n",
    "            i = self.eventIndex[cols[1]]  # 活动\n",
    "            uids.append(u)\n",
    "            i_ids.append(i)\n",
    "            Event_Attendence[i]+=1;\n",
    "            User_Attendence[u]+=1;\n",
    "            R[u, i] = int(cols[4])  # interested\n",
    "            self.mu += R[u, i]\n",
    "            n_records += 1\n",
    "        self.R=R\n",
    "        ftrain.close()\n",
    "        self.mu /= n_records\n",
    "        \n",
    "       \n",
    "        # 请补充完整SVD模型训练过程\n",
    "        # 矩阵训练\n",
    "        \n",
    "        max_iteration=1500;   #最大循环设置为1200次,本来应该设置多点，但是1200看上去SSE也很小了，程序跑得比较慢\n",
    "        lamb= 0.2 #正则系数取0.2\n",
    "        self.SSE=np.zeros(max_iteration)\n",
    "        self.P=np.mat(self.P);\n",
    "        self.Q=np.mat(self.Q);\n",
    "        R=np.mat(R);\n",
    "        learning_rate=0.8 #学习率一开始大一点\n",
    "        bu_matrix=np.zeros((self.n_users,self.n_items));\n",
    "        bi_matrix=np.zeros((self.n_users,self.n_items));\n",
    "        for iter in range (0,max_iteration):\n",
    "            learning_rate*=0.98  #学习率不要太小收敛会比较快\n",
    "            if learning_rate<=0.1:\n",
    "                learning_rate= 0.1;\n",
    "                \n",
    "            error= R-self.P*self.Q-self.mu-bu_matrix-bi_matrix;  #误差矩阵\n",
    "            self.SSE[iter]=(np.multiply(error,error).sum()+lamb*np.multiply(self.P,self.P).sum()+lamb*np.multiply(self.Q,self.Q).sum())+lamb*np.multiply(bu_matrix,bu_matrix).sum()+ lamb*np.multiply(bi_matrix,bi_matrix).sum()           \n",
    "            tempP=self.P+1/self.n_users*learning_rate*error*self.Q.transpose()+lamb*self.P*1/self.n_users;\n",
    "            self.Q=self.Q+1/self.n_items*learning_rate*self.P.transpose()*error+lamb*self.Q*1/self.n_items;\n",
    "            self.P=tempP;\n",
    "            \n",
    "            self.bu=self.bu.reshape(self.n_users,1)\n",
    "            self.bi=self.bi.reshape(1,self.n_items)\n",
    "            #用每一行的总error更新bu\n",
    "            buerror=(error-lamb*bu_matrix).sum(axis=1).reshape(self.n_users,1);\n",
    "            buerror=buerror/self.n_items;\n",
    "            self.bu=self.bu+learning_rate*buerror #更新bu\n",
    "            #用每一列的总error更新bi\n",
    "            bierror=(error-lamb*bi_matrix).sum(axis=0).reshape(1,self.n_items);\n",
    "            bierror=bierror/self.n_users;\n",
    "            self.bi=self.bi+learning_rate*bierror #更新bi\n",
    "            for u in range(1,self.n_users):\n",
    "                self.bi=self.bi.reshape(self.n_items)   #生成bu矩阵\n",
    "                bi_matrix[u,:]=self.bi;\n",
    "            for i in range(1,self.n_items):\n",
    "                self.bu=self.bu.reshape(self.n_users)   #生成bi矩阵\n",
    "                bu_matrix[:,i]=self.bu;\n",
    "            print(self.SSE[iter])\n",
    "            #因为实际上因为用的是矩阵运算，每一次我们更新一整个用户的行或者是一整个事件的列，所以需要除以数量求平均值。\n",
    "        print \"SVD trained finish\"\n",
    "\n",
    "    def pred_SVD(self, uid, i_id):\n",
    "        # 根据当前参数，预测用户uid对Item（i_id）的打分        \n",
    "        self.bi[0,i_id]\n",
    "        self.bu[0,uid]\n",
    "        ans = self.mu + self.bi[0,i_id] + self.bu[0,uid] + np.dot(self.P[uid, :], self.Q[:, i_id])\n",
    "\n",
    "        # 将打分范围控制在0-1之间\n",
    "        if ans > 1:\n",
    "            return 1\n",
    "        elif ans < 0:\n",
    "            return 0\n",
    "        return ans\n",
    "\n",
    "    def sim_cal_UserCF(self, uid1, uid2,user1aver,user2aver):\n",
    "        # 请补充基于用户的协同过滤中的两个用户uid1和uid2之间的相似度（根据两个用户对item打分的相似度）\n",
    "        if user1aver==0 or user2aver==0 or user1aver!=user1aver or user2aver!=user2aver:  #没有评过有效分数，不用算了\n",
    "            return 0\n",
    "        \n",
    "        user1score=self.R[uid1,:];\n",
    "        user1score=user1score.reshape(1,user1score.shape[0])\n",
    "        user2score=self.R[uid2,:];\n",
    "        user2score=user2score.reshape(1,user2score.shape[0])\n",
    "        \n",
    "        cov=np.dot(user1score,user2score.transpose())*(1-user2aver)*(1-user1aver)\n",
    "        varuser1=np.dot((user1score*(1-user1aver)),((user1score*(1-user1aver)).transpose()))\n",
    "        \n",
    "        varuser2=np.dot((user2score*(1-user1aver)),((user2score*(1-user2aver)).transpose()))\n",
    "        similarity= cov/math.sqrt(varuser1)/math.sqrt(varuser2)\n",
    "        if similarity<0:\n",
    "            return 0;\n",
    "        return similarity\n",
    "\n",
    "    def userCFReco(self, userId, eventId):\n",
    "        \"\"\"\n",
    "        根据User-based协同过滤，得到event的推荐度\n",
    "        基本的伪代码思路如下：\n",
    "        for item i\n",
    "          for every other user v that has a preference for i\n",
    "            compute similarity s between u and v\n",
    "            incorporate v's preference for i weighted by s into running aversge\n",
    "        return top items ranked by weighted average\n",
    "        \"\"\"\n",
    "        # 请补充完整代码\n",
    "        useraverscore=np.nan_to_num(self.useraverscore)\n",
    "        ans=useraverscore[userId]\n",
    "        if (self.usersimularity[userId,:].sum()==0):\n",
    "            return 0\n",
    "        ans+=np.dot(self.usersimularity[userId,:],(self.R[:,eventId].transpose()-useraverscore).transpose())/self.usersimularity[userId,:].sum()\n",
    "        return ans\n",
    "\n",
    "    def sim_cal_ItemCF(self, i_id1, i_id2,item1aver,item2aver):\n",
    "        # 计算Item i_id1和i_id2之间的相似性\n",
    "        # 请补充完整代码\n",
    "        if item1aver==0 or item2aver==1 or item1aver==1 or item2aver==0 or item1aver!=item1aver or item2aver!=item2aver:  #没有评过有效分数，不用算了\n",
    "            return 0\n",
    "        \n",
    "        item1score=self.R[:,i_id1];\n",
    "        item1score=item1score.reshape(1,item1score.shape[0])\n",
    "        item2score=self.R[:,i_id2];\n",
    "        item2score=item2score.reshape(1,item2score.shape[0])\n",
    "        \n",
    "        cov=np.dot(item1score,item2score.transpose())*(1-item2aver)*(1-item1aver)\n",
    "        \n",
    "        varitem1=np.dot((item1score*(1-item1aver)),((item1score*(1-item1aver)).transpose()))\n",
    "        \n",
    "        varitem2=np.dot((item2score*(1-item2aver)),((item2score*(1-item2aver)).transpose()))  \n",
    "        #当中存在事件平均分是1的，按公式计算分母会变成0。我觉得这种没什么参考价值，就RETURN一个0算了。\n",
    "        \n",
    "        similarity= cov/math.sqrt(varitem1)/math.sqrt(varitem2)\n",
    "        if similarity<0:\n",
    "            return 0;\n",
    "        return similarity\n",
    "\n",
    "    # return num/den  \n",
    "\n",
    "    def eventCFReco(self, userId, eventId):\n",
    "        \"\"\"\n",
    "        根据基于物品的协同过滤，得到Event的推荐度\n",
    "        基本的伪代码思路如下：\n",
    "        for item i \n",
    "            for every item j tht u has a preference for\n",
    "                compute similarity s between i and j\n",
    "                add u's preference for j weighted by s to a running average\n",
    "        return top items, ranked by weighted average\n",
    "        \"\"\"\n",
    "       # 请补充完整代码\n",
    "        eventaverscore=np.nan_to_num(self.itemaverscore)\n",
    "        ans=eventaverscore[eventId]\n",
    "        if (self.itemsimularity[eventId,:].sum()==0): #完全没有相似性可以找，就返回0试试看吧\n",
    "            return 0\n",
    "        ans+=np.dot(self.itemsimularity[eventId,:],(RS.R[userId,:]-eventaverscore).transpose())/self.itemsimularity[:,eventId].sum()\n",
    "        return ans\n",
    "\n",
    "    def svdCFReco(self, userId, eventId):\n",
    "        # 基于模型的协同过滤, SVD++/LFM\n",
    "        u = self.userIndex[userId]\n",
    "        i = self.eventIndex[eventId]\n",
    "        \n",
    "        \n",
    "        return self.pred_SVD(u, i)\n",
    "\n",
    "    def userReco(self, userId, eventId):\n",
    "        \"\"\"\n",
    "        类似基于User-based协同过滤，只是用户之间的相似度由用户本身的属性得到，计算event的推荐度\n",
    "        基本的伪代码思路如下：\n",
    "        for item i\n",
    "          for every other user v that has a preference for i\n",
    "            compute similarity s between u and v\n",
    "            incorporate v's preference for i weighted by s into running aversge\n",
    "        return top items ranked by weighted average\n",
    "        \"\"\"\n",
    "        i = self.userIndex[userId]\n",
    "        j = self.eventIndex[eventId]\n",
    "\n",
    "        vs = self.userEventScores[:, j]\n",
    "        sims = self.userSimMatrix[i, :]\n",
    "\n",
    "        prod = sims * vs\n",
    "\n",
    "        try:\n",
    "            return prod[0, 0] - self.userEventScores[i, j]\n",
    "        except IndexError:\n",
    "            return 0\n",
    "\n",
    "    def eventReco(self, userId, eventId):\n",
    "        \"\"\"\n",
    "        类似基于Item-based协同过滤，只是item之间的相似度由item本身的属性得到，计算Event的推荐度\n",
    "        基本的伪代码思路如下：\n",
    "        for item i \n",
    "          for every item j that u has a preference for\n",
    "            compute similarity s between i and j\n",
    "            add u's preference for j weighted by s to a running average\n",
    "        return top items, ranked by weighted average\n",
    "        \"\"\"\n",
    "        i = self.userIndex[userId]\n",
    "        j = self.eventIndex[eventId]\n",
    "        js = self.userEventScores[i, :]\n",
    "        psim = self.eventPropSim[:, j]\n",
    "        csim = self.eventContSim[:, j]\n",
    "        pprod = js * psim\n",
    "        cprod = js * csim\n",
    "\n",
    "        pscore = 0\n",
    "        cscore = 0\n",
    "        try:\n",
    "            pscore = pprod[0, 0] - self.userEventScores[i, j]\n",
    "        except IndexError:\n",
    "            pass\n",
    "        try:\n",
    "            cscore = cprod[0, 0] - self.userEventScores[i, j]\n",
    "        except IndexError:\n",
    "            pass\n",
    "        return pscore, cscore\n",
    "\n",
    "    def userPop(self, userId):\n",
    "        \"\"\"\n",
    "        基于用户的朋友个数来推断用户的社交程度\n",
    "        主要的考量是如果用户的朋友非常多，可能会更倾向于参加各种社交活动\n",
    "        \"\"\"\n",
    "        if self.userIndex.has_key(userId):\n",
    "            i = self.userIndex[userId]\n",
    "            try:\n",
    "                return self.numFriends[0, i]\n",
    "            except IndexError:\n",
    "                return 0\n",
    "        else:\n",
    "            return 0\n",
    "\n",
    "    def friendInfluence(self, userId):\n",
    "        \"\"\"\n",
    "        朋友对用户的影响\n",
    "        主要考虑用户所有的朋友中，有多少是非常喜欢参加各种社交活动/event的\n",
    "        用户的朋友圈如果都积极参与各种event，可能会对当前用户有一定的影响\n",
    "        \"\"\"\n",
    "        nusers = np.shape(self.userFriends)[1]\n",
    "        i = self.userIndex[userId]\n",
    "        return (self.userFriends[i, :].sum(axis=0) / nusers)[0, 0]\n",
    "\n",
    "    def eventPop(self, eventId):\n",
    "        \"\"\"\n",
    "        本活动本身的热度\n",
    "        主要是通过参与的人数来界定的\n",
    "        \"\"\"\n",
    "        i = self.eventIndex[eventId]\n",
    "        return self.eventPopularity[i, 0]\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 62,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "def generateRSData(RS, train=True, header=True):\n",
    "    \"\"\"\n",
    "    把前面user-based协同过滤 和 item-based协同过滤，以及各种热度和影响度作为特征组合在一起\n",
    "    生成新的训练数据，用于分类器分类使用\n",
    "    \"\"\"\n",
    "    fn = \"train.csv\" if train else \"test.csv\"\n",
    "    fin = open(fn, 'rb')\n",
    "    fout = open(\"RS_\" + fn, 'wb')\n",
    "\n",
    "    # 忽略第一行（列名字）\n",
    "    fin.readline().strip().split(\",\")\n",
    "\n",
    "    # write output header\n",
    "    if header:\n",
    "        ocolnames = [\"invited\", \"userCF_reco\", \"evtCF_reco\", \"svdCF_reco\", \"user_reco\", \"evt_p_reco\",\n",
    "                     \"evt_c_reco\", \"user_pop\", \"frnd_infl\", \"evt_pop\"]\n",
    "        if train:\n",
    "            ocolnames.append(\"interested\")\n",
    "            ocolnames.append(\"not_interested\")\n",
    "        fout.write(\",\".join(ocolnames) + \"\\n\")\n",
    "\n",
    "    ln = 0\n",
    "    userCFcounter=0;\n",
    "    eventCFcounter=0;\n",
    "    svdCFcounter=0;\n",
    "    evt_p_reco_counter=0;\n",
    "    user_reco_counter=0;\n",
    "    for line in fin:\n",
    "        ln += 1\n",
    "        if ln % 500 == 0:\n",
    "            print \"%s:%d (userId, eventId)=(%s, %s)\" % (fn, ln, userId, eventId)\n",
    "            print \"基于用户推荐非0值\" ,userCFcounter\n",
    "            print '基于事件推荐非0值' ,eventCFcounter\n",
    "            print '基于模型推荐非0值', svdCFcounter\n",
    "            print '基于用户属性推荐非0值',user_reco_counter\n",
    "            print '基于物品属性推荐非0值',  evt_p_reco_counter \n",
    "        cols = line.strip().split(\",\")\n",
    "        userId = cols[0]\n",
    "        eventId = cols[1]\n",
    "        invited = cols[2]\n",
    "        userIndex = cPickle.load(open(\"PE_userIndex.pkl\", 'rb'))\n",
    "        uid=userIndex[userId]\n",
    "        eventIndex = cPickle.load(open(\"PE_eventIndex.pkl\", 'rb'))\n",
    "        eid=eventIndex[eventId]\n",
    "        userCF_reco = RS.userCFReco(uid, eid)\n",
    "        if userCF_reco> (0.2 if train else 0.05):\n",
    "            userCFcounter+=1;\n",
    "        itemCF_reco = RS.eventCFReco(uid, eid)\n",
    "        if itemCF_reco>(0.2 if train else 0.05):\n",
    "            eventCFcounter+=1;\n",
    "        svdCF_reco = RS.svdCFReco(userId, eventId)\n",
    "        if svdCF_reco>0.005:\n",
    "            svdCFcounter+=1\n",
    "        user_reco = RS.userReco(userId, eventId)\n",
    "        if user_reco>(0.2 if train else 0.05):\n",
    "            user_reco_counter+=1;\n",
    "        evt_p_reco, evt_c_reco = RS.eventReco(userId, eventId)\n",
    "        if evt_p_reco_counter>0.0001:\n",
    "            evt_p_reco_counter+=1\n",
    "        user_pop = RS.userPop(userId)\n",
    "\n",
    "        frnd_infl = RS.friendInfluence(userId)\n",
    "        evt_pop = RS.eventPop(eventId)\n",
    "        ocols = [invited, userCF_reco, itemCF_reco, svdCF_reco, user_reco, evt_p_reco,\n",
    "                 evt_c_reco, user_pop, frnd_infl, evt_pop]\n",
    "\n",
    "        if train:\n",
    "            ocols.append(cols[4])  # interested\n",
    "            ocols.append(cols[5])  # not_interested\n",
    "        fout.write(\",\".join(map(lambda x: str(x), ocols)) + \"\\n\")\n",
    "\n",
    "    fin.close()\n",
    "    fout.close()\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "SVD Train...\n",
      "12337139.359761259\n",
      "24372149.157098617\n",
      "36448974.13122219\n",
      "41393109.83182488\n",
      "29384080.378899585\n",
      "15164819.33810032\n",
      "6318070.181629916\n",
      "2406600.3762019696\n",
      "952432.1233131138\n",
      "478429.1892009155\n",
      "341035.9438509609\n",
      "304176.1260042352\n",
      "293683.360049856\n",
      "289315.07135411724\n",
      "286219.741569505\n",
      "283409.702397421\n",
      "280699.8362849368\n",
      "278061.1673839936\n",
      "275486.5765580365\n",
      "272973.0091953558\n",
      "270517.8088900835\n",
      "268118.61747517076\n",
      "265773.25625126786\n",
      "263479.7204103087\n",
      "261236.15799471526\n",
      "259040.85514923584\n",
      "256892.22214996075\n",
      "254788.78102645196\n",
      "252729.15445065426\n",
      "250712.05578187414\n",
      "248736.28014309728\n",
      "246800.6964211831\n",
      "244904.24009486102\n",
      "243045.9068049417\n",
      "241224.74659024755\n",
      "239439.8587209413\n",
      "237690.38706805668\n",
      "235975.51595442148\n",
      "234294.46643780934\n",
      "232646.49298221854\n",
      "231030.88047762858\n",
      "229446.94157264626\n",
      "227894.01428801077\n",
      "226371.45988215535\n",
      "224878.6609429206\n",
      "223415.01968208214\n",
      "221979.95641169976\n",
      "220572.90818338652\n",
      "219193.32757347595\n",
      "217840.68159876944\n",
      "216514.45074907172\n",
      "215214.1281241083\n",
      "213939.21866364687\n",
      "212689.23846080207\n",
      "211463.7141494684\n",
      "210262.1823577884\n",
      "209084.1892203606\n",
      "207929.2899426287\n",
      "206797.04841162005\n",
      "205687.03684773034\n",
      "204598.8354928667\n",
      "203532.03233072074\n",
      "202486.22283539566\n",
      "201461.00974502528\n",
      "200456.0028573661\n",
      "199470.81884468504\n",
      "198505.08108555572\n",
      "197558.41951143258\n",
      "196630.4704661272\n",
      "195720.87657650205\n",
      "194829.28663291363\n",
      "193955.35547808209\n",
      "193098.743903252\n",
      "192259.11855060566\n",
      "191436.15182106267\n",
      "190629.52178665827\n",
      "189838.9121068409\n",
      "189064.0119480751\n",
      "188304.51590625042\n",
      "187560.123931434\n",
      "186830.54125459862\n",
      "186115.4783159786\n",
      "185414.65069478925\n",
      "184727.77904006332\n",
      "184054.58900240174\n",
      "183394.81116647815\n",
      "182748.1809841573\n",
      "182114.4387081108\n",
      "181493.32932584832\n",
      "180884.60249408416\n",
      "180288.0124733933\n",
      "179703.31806311192\n",
      "179130.2825364623\n",
      "178568.6735758708\n",
      "178018.26320849505\n",
      "177478.82774193538\n",
      "176950.14770015376\n",
      "176432.00775959974\n",
      "175924.19668557995\n",
      "175426.50726885424\n",
      "174938.73626251874\n",
      "174460.68431916978\n",
      "173992.15592839418\n",
      "173532.3087878441\n",
      "173072.56211570138\n",
      "172612.9193377024\n",
      "172153.38389860032\n",
      "171693.95926212135\n",
      "171234.64891108638\n",
      "170775.45634756619\n",
      "170316.38509301853\n",
      "169857.43868837334\n",
      "169398.62069406643\n",
      "168939.93469001443\n",
      "168481.38427554874\n",
      "168022.97306930477\n",
      "167564.70470907626\n",
      "167106.58285164944\n",
      "166648.61117260501\n",
      "166190.7933661101\n",
      "165733.1331446955\n",
      "165275.63423901398\n",
      "164818.30039759882\n",
      "164361.1353866117\n",
      "163904.14298958052\n",
      "163447.32700713887\n",
      "162990.6912567583\n",
      "162534.23957247497\n",
      "162077.97580461888\n",
      "161621.90381953702\n",
      "161166.02749931545\n",
      "160710.3507414996\n",
      "160254.8774588128\n",
      "159799.611578874\n",
      "159344.55704391462\n",
      "158889.71781049203\n",
      "158435.09784920572\n",
      "157980.70114440809\n",
      "157526.53169391854\n",
      "157072.59350873373\n",
      "156618.89061273917\n",
      "156165.42704241702\n",
      "155712.20684655738\n",
      "155259.2340859662\n",
      "154806.51283317292\n",
      "154354.04717213675\n",
      "153901.84119795525\n",
      "153449.89901656882\n",
      "152998.22474446608\n",
      "152546.82250839175\n",
      "152095.69644504704\n",
      "151644.8507007975\n",
      "151194.2894313741\n",
      "150744.01680157974\n",
      "150294.03698498686\n",
      "149844.35416364716\n",
      "149394.97252778756\n",
      "148945.89627551584\n",
      "148497.12961252156\n",
      "148048.6767517769\n",
      "147600.54191323963\n",
      "147152.72932354972\n",
      "146705.2432157391\n",
      "146258.0878289213\n",
      "145811.2674079999\n",
      "145364.78620336752\n",
      "144918.64847060243\n",
      "144472.8584701749\n",
      "144027.42046714394\n",
      "143582.33873085617\n",
      "143137.61753464944\n",
      "142693.26115555322\n",
      "142249.27387398534\n",
      "141805.65997345594\n",
      "141362.42374026813\n",
      "140919.569463216\n",
      "140477.1014332887\n",
      "140035.02394336963\n",
      "139593.34128793844\n",
      "139152.0577627724\n",
      "138711.17766464985\n",
      "138270.70529104985\n",
      "137830.64493985515\n",
      "137391.0009090574\n",
      "136951.7774964579\n",
      "136512.97899937173\n",
      "136074.60971433242\n",
      "135636.67393679568\n",
      "135199.17596084456\n",
      "134762.12007889556\n",
      "134325.51058140362\n",
      "133889.35175656798\n",
      "133453.647890042\n",
      "133018.4032646375\n",
      "132583.62216003484\n",
      "132149.30885249237\n",
      "131715.46761455445\n",
      "131282.10271476163\n",
      "130849.21841736417\n",
      "130416.81898203107\n",
      "129984.90866356393\n",
      "129553.49171161035\n",
      "129122.57237037629\n",
      "128692.15487834463\n",
      "128262.2434679876\n",
      "127832.84236548447\n",
      "127403.95579044108\n",
      "126975.58795560534\n",
      "126547.74306658996\n",
      "126120.42532159109\n",
      "125693.63891110996\n",
      "125267.38801767708\n",
      "124841.67681557435\n",
      "124416.5094705609\n",
      "123991.89013959738\n",
      "123567.82297057612\n",
      "123144.3121020467\n",
      "122721.36166294664\n",
      "122298.9757723314\n",
      "121877.15853910604\n",
      "121455.91406176084\n",
      "121035.24642810161\n",
      "120615.15971498954\n",
      "120195.6579880752\n",
      "119776.74530153778\n",
      "119358.42569782678\n",
      "118940.70320740069\n",
      "118523.58184847097\n",
      "118107.0656267452\n",
      "117691.15853517436\n",
      "117275.86455369716\n",
      "116861.18764899025\n",
      "116447.13177421938\n",
      "116033.70086878847\n",
      "115620.89885809366\n",
      "115208.729653279\n",
      "114797.19715099246\n",
      "114386.30523314218\n",
      "113976.05776665936\n",
      "113566.45860325595\n",
      "113157.51157919061\n",
      "112749.22051503234\n",
      "112341.58921542601\n",
      "111934.62146886243\n",
      "111528.3210474465\n",
      "111122.69170667011\n",
      "110717.7371851858\n",
      "110313.46120458131\n",
      "109909.86746915747\n",
      "109506.95966570676\n",
      "109104.74146329495\n",
      "108703.216513044\n",
      "108302.38844791634\n",
      "107902.26088250108\n",
      "107502.83741280479\n",
      "107104.12161603896\n",
      "106706.11705041604\n",
      "106308.8272549415\n",
      "105912.2557492117\n",
      "105516.40603321219\n",
      "105121.28158711841\n",
      "104726.88587109855\n",
      "104333.22232511797\n",
      "103940.29436874688\n",
      "103548.10540096834\n",
      "103156.6587999908\n",
      "102765.95792305979\n",
      "102376.00610627359\n",
      "101986.80666440321\n",
      "101598.36289070749\n",
      "101210.67805675959\n",
      "100823.7554122677\n",
      "100437.59818490387\n",
      "100052.20958013041\n",
      "99667.59278103191\n",
      "99283.75094814817\n",
      "98900.68721930865\n",
      "98518.4047094701\n",
      "98136.90651055722\n",
      "97756.19569130329\n",
      "97376.2752970958\n",
      "96997.14834982133\n",
      "96618.81784771662\n",
      "96241.28676521768\n",
      "95864.55805281499\n",
      "95488.6346369084\n",
      "95113.51941966522\n",
      "94739.21527888102\n",
      "94365.72506784325\n",
      "93993.0516151945\n",
      "93621.19772480265\n",
      "93250.16617562897\n",
      "92879.95972160046\n",
      "92510.58109148641\n",
      "92142.03298877296\n",
      "91774.31809154445\n",
      "91407.43905236482\n",
      "91041.39849816135\n",
      "90676.19903011218\n",
      "90311.84322353496\n",
      "89948.33362777873\n",
      "89585.6727661165\n",
      "89223.8631356435\n",
      "88862.90720717561\n",
      "88502.8074251481\n",
      "88143.5662075232\n",
      "87785.18594569224\n",
      "87427.66900438748\n",
      "87071.01772159028\n",
      "86715.23440844537\n",
      "86360.32134917773\n",
      "86006.28080100883\n",
      "85653.11499407857\n",
      "85300.8261313667\n",
      "84949.41638862116\n",
      "84598.88791428201\n",
      "84249.24282941545\n",
      "83900.48322764324\n",
      "83552.61117508064\n",
      "83205.62871027229\n",
      "82859.53784413167\n",
      "82514.34055988536\n",
      "82170.03881301588\n",
      "81826.63453120943\n",
      "81484.12961430634\n",
      "81142.52593425178\n",
      "80801.82533505037\n",
      "80462.02963272312\n",
      "80123.1406152666\n",
      "79785.16004261396\n",
      "79448.08964659894\n",
      "79111.9311309227\n",
      "78776.68617112076\n",
      "78442.35641453578\n",
      "78108.94348028974\n",
      "77776.44895925885\n",
      "77444.87441405295\n",
      "77114.22137899557\n",
      "76784.4913601049\n",
      "76455.68583507993\n",
      "76127.80625328732\n",
      "75800.85403575105\n",
      "75474.83057514354\n",
      "75149.73723577996\n",
      "74825.57535361487\n",
      "74502.3462362396\n",
      "74180.05116288443\n",
      "73858.69138442003\n",
      "73538.26812336373\n",
      "73218.78257388689\n",
      "72900.2359018237\n",
      "72582.62924468354\n",
      "72265.96371166519\n",
      "71950.2403836721\n",
      "71635.4603133321\n",
      "71321.62452501571\n",
      "71008.73401486105\n",
      "70696.78975079699\n",
      "70385.7926725702\n",
      "70075.74369177475\n",
      "69766.64369188205\n",
      "69458.49352827496\n",
      "69151.29402828147\n",
      "68845.04599121418\n",
      "68539.75018840627\n",
      "68235.40736325609\n",
      "67932.01823126733\n",
      "67629.58348009664\n",
      "67328.1037695991\n",
      "67027.57973187843\n",
      "66728.01197133718\n",
      "66429.40106473009\n",
      "66131.74756121961\n",
      "65835.0519824316\n",
      "65539.31482251454\n",
      "65244.53654820043\n",
      "64950.71759886667\n",
      "64657.85838660055\n",
      "64365.95929626527\n",
      "64075.02068556763\n",
      "63785.042885127856\n",
      "63496.026198551604\n",
      "63207.97090250239\n",
      "62920.877246776035\n",
      "62634.745454379154\n",
      "62349.575721605695\n",
      "62065.368218117845\n",
      "61782.12308702782\n",
      "61499.8404449809\n",
      "61218.520382240284\n",
      "60938.162962774724\n",
      "60658.76822434603\n",
      "60380.33617859816\n",
      "60102.866811150205\n",
      "59826.36008168878\n",
      "59550.81592406119\n",
      "59276.23424637377\n",
      "59002.61493108759\n",
      "58729.95783511786\n",
      "58458.2627899349\n",
      "58187.529601665534\n",
      "57917.758051196215\n",
      "57648.947894278186\n",
      "57381.09886163385\n",
      "57114.210659062905\n",
      "56848.282967552615\n",
      "56583.31544338731\n",
      "56319.30771826007\n",
      "56056.259399385024\n",
      "55794.17006961179\n",
      "55533.03928754106\n",
      "55272.866587640194\n",
      "55013.65148036157\n",
      "54755.39345226215\n",
      "54498.091966121836\n",
      "54241.746461066985\n",
      "53986.35635269107\n",
      "53731.92103317904\n",
      "53478.43987143193\n",
      "53225.9122131925\n",
      "52974.337381172016\n",
      "52723.71467517816\n",
      "52474.04337224418\n",
      "52225.322726758415\n",
      "51977.55197059574\n",
      "51730.730313248554\n",
      "51484.85694196011\n",
      "51239.9310218591\n",
      "50995.95169609291\n",
      "50752.918085963895\n",
      "50510.82929106599\n",
      "50269.68438942163\n",
      "50029.482437620405\n",
      "49790.222470957364\n",
      "49551.90350357363\n",
      "49314.52452859622\n",
      "49078.08451827965\n",
      "48842.58242414818\n",
      "48608.01717713861\n",
      "48374.38768774374\n",
      "48141.69284615606\n",
      "47909.931522413535\n",
      "47679.1025665444\n",
      "47449.20480871403\n",
      "47220.23705937114\n",
      "46992.19810939531\n",
      "46765.08673024518\n",
      "46538.901674106615\n",
      "46313.64167404233\n",
      "46089.30544414066\n",
      "45865.89167966672\n",
      "45643.399057212046\n",
      "45421.82623484619\n",
      "45201.17185226847\n",
      "44981.43453095891\n",
      "44762.61287433216\n",
      "44544.70546788873\n",
      "44327.710879369435\n",
      "44111.62765890777\n",
      "43896.45433918526\n",
      "43682.18943558393\n",
      "43468.83144634261\n",
      "43256.378852710244\n",
      "43044.830119102\n",
      "42834.18369325431\n",
      "42624.43800638062\n",
      "42415.591473327215\n",
      "42207.642492729094\n",
      "42000.58944716654\n",
      "41794.43070332115\n",
      "41589.16461213345\n",
      "41384.78950895837\n",
      "41181.30371372322\n",
      "40978.705531084124\n",
      "40776.993250583386\n",
      "40576.16514680656\n",
      "40376.21947954023\n",
      "40177.15449392865\n",
      "39978.9684206314\n",
      "39781.65947598141\n",
      "39585.22586214119\n",
      "39389.66576726148\n",
      "39194.97736563782\n",
      "39001.15881786858\n",
      "38808.20827101141\n",
      "38616.123858741645\n",
      "38424.90370150819\n",
      "38234.54590669191\n",
      "38045.04856876191\n",
      "37856.40976943212\n",
      "37668.62757781905\n",
      "37481.70005059733\n",
      "37295.62523215661\n",
      "37110.40115475822\n",
      "36926.02583869023\n",
      "36742.49729242455\n",
      "36559.813512771514\n",
      "36377.972485036036\n",
      "36196.97218317239\n",
      "36016.810569939546\n",
      "35837.48559705529\n",
      "35658.99520535141\n",
      "35481.33732492718\n",
      "35304.509875303345\n",
      "35128.510765575826\n",
      "34953.33789456871\n",
      "34778.98915098735\n",
      "34605.46241357031\n",
      "34432.755551242364\n",
      "34260.866423265536\n",
      "34089.7928793908\n",
      "33919.5327600093\n",
      "33750.08389630259\n",
      "33581.44411039294\n",
      "33413.611215493234\n",
      "33246.58301605634\n",
      "33080.357307923725\n",
      "32914.931878474235\n",
      "32750.304506771914\n",
      "32586.47296371345\n",
      "32423.43501217547\n",
      "32261.188407160684\n",
      "32099.730895944325\n",
      "31939.060218219412\n",
      "31779.174106241888\n",
      "31620.070284974805\n",
      "31461.746472232888\n",
      "31304.2003788253\n",
      "31147.42970869865\n",
      "30991.43215907977\n",
      "30836.205420616476\n",
      "30681.747177519326\n",
      "30528.055107702403\n",
      "30375.126882922683\n",
      "30222.96016891954\n",
      "30071.552625553668\n",
      "29920.901906944833\n",
      "29771.005661610194\n",
      "29621.86153259984\n",
      "29473.46715763425\n",
      "29325.820169239327\n",
      "29178.918194881197\n",
      "29032.758857100765\n",
      "28887.339773647225\n",
      "28742.658557610917\n",
      "28598.712817555614\n",
      "28455.50015765024\n",
      "28313.01817779943\n",
      "28171.26447377413\n",
      "28030.236637340633\n",
      "27889.932256389955\n",
      "27750.34891506502\n",
      "27611.484193889155\n",
      "27473.335669891516\n",
      "27335.900916734005\n",
      "27199.177504835767\n",
      "27063.163001498135\n",
      "26927.854971027846\n",
      "26793.25097486021\n",
      "26659.348571681618\n",
      "26526.145317550436\n",
      "26393.63876601798\n",
      "26261.826468248684\n",
      "26130.705973138618\n",
      "26000.27482743475\n",
      "25870.53057585154\n",
      "25741.47076118913\n",
      "25613.09292444789\n",
      "25485.394604944988\n",
      "25358.37334042801\n",
      "25232.026667189166\n",
      "25106.352120178424\n",
      "24981.34723311478\n",
      "24857.009538598373\n",
      "24733.336568220642\n",
      "24610.325852674374\n",
      "24487.97492186234\n",
      "24366.2813050056\n",
      "24245.242530750453\n",
      "24124.856127275685\n",
      "24005.119622397535\n",
      "23886.03054367485\n",
      "23767.58641851326\n",
      "23649.784774268308\n",
      "23532.623138347873\n",
      "23416.099038313907\n",
      "23300.210001983087\n",
      "23184.953557526864\n",
      "23070.327233570548\n",
      "22956.328559291804\n",
      "22842.955064517868\n",
      "22730.204279822538\n",
      "22618.073736621838\n",
      "22506.560967269084\n",
      "22395.663505149085\n",
      "22285.37888477159\n",
      "22175.704641863544\n",
      "22066.638313461477\n",
      "21958.17743800157\n",
      "21850.31955541018\n",
      "21743.062207193216\n",
      "21636.40293652409\n",
      "21530.339288331805\n",
      "21424.86880938732\n",
      "21319.989048389587\n",
      "21215.69755605087\n",
      "21111.99188518089\n",
      "21008.86959077009\n",
      "20906.32823007272\n",
      "20804.365362688168\n",
      "20702.978550642307\n",
      "20602.165358467562\n",
      "20501.92335328224\n",
      "20402.25010486915\n",
      "20303.14318575322\n",
      "20204.600171278493\n",
      "20106.618639684173\n",
      "20009.196172180033\n",
      "19912.330353020676\n",
      "19816.01876957932\n",
      "19720.259012420895\n",
      "19625.048675373575\n",
      "19530.38535560047\n",
      "19436.26665366986\n",
      "19342.69017362502\n",
      "19249.653523052777\n",
      "19157.154313151907\n",
      "19065.190158800324\n",
      "18973.75867862117\n",
      "18882.85749504905\n",
      "18792.484234394622\n",
      "18702.636526908813\n",
      "18613.312006845954\n",
      "18524.508312526657\n",
      "18436.223086399274\n",
      "18348.453975101143\n",
      "18261.198629518676\n",
      "18174.45470484682\n",
      "18088.219860647834\n",
      "18002.491760909244\n",
      "17917.268074100626\n",
      "17832.54647323073\n",
      "17748.324635902554\n",
      "17664.600244368405\n",
      "17581.3709855842\n",
      "17498.63455126262\n",
      "17416.388637926095\n",
      "17334.63094695843\n",
      "17253.359184656183\n",
      "17172.571062279083\n",
      "17092.264296099787\n",
      "17012.436607452757\n",
      "16933.085722782755\n",
      "16854.20937369225\n",
      "16775.805296988226\n",
      "16697.871234728525\n",
      "16620.404934267055\n",
      "16543.404148298636\n",
      "16466.866634903\n",
      "16390.79015758798\n",
      "16315.172485332312\n",
      "16240.011392627632\n",
      "16165.304659519363\n",
      "16091.050071647558\n",
      "16017.245420286847\n",
      "15943.888502385362\n",
      "15870.977120603515\n",
      "15798.50908335177\n",
      "15726.482204827771\n",
      "15654.894305053065\n",
      "15583.743209908735\n",
      "15513.026751170899\n",
      "15442.742766544961\n",
      "15372.889099700024\n",
      "15303.463600301546\n",
      "15234.46412404456\n",
      "15165.888532685414\n",
      "15097.734694073191\n",
      "15030.000482180543\n",
      "14962.683777133752\n",
      "14895.782465242215\n",
      "14829.294439027633\n",
      "14763.217597251893\n",
      "14697.54984494523\n",
      "14632.289093432839\n",
      "14567.433260361748\n",
      "14502.980269726642\n",
      "14438.928051894982\n",
      "14375.274543632106\n",
      "14312.017688124943\n",
      "14249.155435006067\n",
      "14186.685740376251\n",
      "14124.606566827239\n",
      "14062.91588346344\n",
      "14001.611665923312\n",
      "13940.691896400143\n",
      "13880.154563662272\n",
      "13819.997663072569\n",
      "13760.219196607832\n",
      "13700.817172877236\n",
      "13641.78960714038\n",
      "13583.134521324726\n",
      "13524.849944042806\n",
      "13466.933910608474\n",
      "13409.384463053048\n",
      "13352.199650140654\n",
      "13295.377527383103\n",
      "13238.916157054507\n",
      "13182.813608205031\n",
      "13127.067956674358\n",
      "13071.677285104708\n",
      "13016.639682953386\n",
      "12961.953246504385\n",
      "12907.616078880279\n",
      "12853.626290053115\n",
      "12799.981996854785\n",
      "12746.681322987424\n",
      "12693.722399032817\n",
      "12641.103362461507\n",
      "12588.822357641724\n",
      "12536.877535847576\n",
      "12485.267055266639\n",
      "12433.98908100771\n",
      "12383.041785107405\n",
      "12332.423346536842\n",
      "12282.131951207768\n",
      "12232.165791978048\n",
      "12182.523068656908\n",
      "12133.201988009907\n",
      "12084.200763763281\n",
      "12035.517616607707\n",
      "11987.1507742023\n",
      "11939.09847117759\n",
      "11891.35894913805\n",
      "11843.930456665086\n",
      "11796.811249318536\n",
      "11749.999589638626\n",
      "11703.493747146984\n",
      "11657.291998347675\n",
      "11611.39262672769\n",
      "11565.793922756959\n",
      "11520.494183888273\n",
      "11475.491714556649\n",
      "11430.784826178375\n",
      "11386.371837149669\n",
      "11342.251072845113\n",
      "11298.4208656156\n",
      "11254.879554786192\n",
      "11211.625486653078\n",
      "11168.65701448095\n",
      "11125.972498499457\n",
      "11083.57030589967\n",
      "11041.448810830154\n",
      "10999.606394392395\n",
      "10958.041444636518\n",
      "10916.752356556337\n",
      "10875.737532083853\n",
      "10834.99538008403\n",
      "10794.524316348947\n",
      "10754.322763591466\n",
      "10714.389151439034\n",
      "10674.721916426999\n",
      "10635.319501991416\n",
      "10596.180358461988\n",
      "10557.302943054523\n",
      "10518.685719862964\n",
      "10480.327159851486\n",
      "10442.225740845986\n",
      "10404.379947525718\n",
      "10366.78827141408\n",
      "10329.449210869801\n",
      "10292.361271077392\n",
      "10255.522964037602\n",
      "10218.932808557456\n",
      "10182.589330240171\n",
      "10146.491061474853\n",
      "10110.636541426007\n",
      "10075.024316022345\n",
      "10039.65293794608\n",
      "10004.520966621596\n",
      "9969.626968203844\n",
      "9934.969515566645\n",
      "9900.54718829086\n",
      "9866.358572652081\n",
      "9832.402261608426\n",
      "9798.67685478787\n",
      "9765.180958475525\n",
      "9731.91318560072\n",
      "9698.872155723679\n",
      "9666.05649502236\n",
      "9633.464836278743\n",
      "9601.095818865218\n",
      "9568.948088730565\n",
      "9537.0202983859\n",
      "9505.311106890455\n",
      "9473.81917983688\n",
      "9442.543189336957\n",
      "9411.481814006553\n",
      "9380.63373895064\n",
      "9349.997655748399\n",
      "9319.572262437589\n",
      "9289.356263499432\n",
      "9259.34836984272\n",
      "9229.54729878816\n",
      "9199.951774052552\n",
      "9170.560525732673\n",
      "9141.372290288873\n",
      "9112.385810529056\n",
      "9083.599835591964\n",
      "9055.013120930626\n",
      "9026.62442829554\n",
      "8998.432525717948\n",
      "8970.436187492598\n",
      "8942.634194160693\n",
      "8915.025332492729\n",
      "8887.608395470874\n",
      "8860.382182271638\n",
      "8833.345498248149\n",
      "8806.497154912471\n",
      "8779.835969917756\n",
      "8753.36076704013\n",
      "8727.070376160855\n",
      "8700.963633248011\n",
      "8675.039380338192\n",
      "8649.296465518244\n",
      "8623.733742906712\n",
      "8598.350072635254\n",
      "8573.14432083003\n",
      "8548.115359592939\n",
      "8523.262066982783\n",
      "8498.58332699625\n",
      "8474.078029549077\n",
      "8449.745070456725\n",
      "8425.583351415476\n",
      "8401.591779982913\n",
      "8377.76926955878\n",
      "8354.114739365516\n",
      "8330.62711442878\n",
      "8307.30532555784\n",
      "8284.148309326192\n",
      "8261.15500805161\n",
      "8238.32436977654\n",
      "8215.655348248349\n",
      "8193.146902899354\n",
      "8170.797998826987\n",
      "8148.607606773812\n",
      "8126.574703107435\n",
      "8104.698269800509\n",
      "8082.977294410573\n",
      "8061.410770059899\n",
      "8039.997695415204\n",
      "8018.737074667437\n",
      "7997.62791751145\n",
      "7976.669239125757\n",
      "7955.860060151919\n",
      "7935.199406674264\n",
      "7914.686310199524\n",
      "7894.319807636008\n",
      "7874.098941273451\n",
      "7854.022758762245\n",
      "7834.090313092849\n",
      "7814.300662575244\n",
      "7794.652870818182\n",
      "7775.146006708683\n",
      "7755.779144391224\n",
      "7736.5513632469565\n",
      "7717.461747873169\n",
      "7698.509388062403\n",
      "7679.693378781641\n",
      "7661.012820151733\n",
      "7642.466817426307\n",
      "7624.054480971176\n",
      "7605.77492624348\n",
      "7587.627273770732\n",
      "7569.610649130077\n",
      "7551.724182927542\n",
      "7533.967010776905\n",
      "7516.338273279121\n",
      "7498.837116001254\n",
      "7481.462689455719\n",
      "7464.214149079476\n",
      "7447.090655212936\n",
      "7430.091373079331\n",
      "7413.215472763803\n",
      "7396.462129192435\n",
      "7379.830522111532\n",
      "7363.319836066708\n",
      "7346.929260382052\n",
      "7330.657989139368\n",
      "7314.5052211572765\n",
      "7298.470159970448\n",
      "7282.5520138088\n",
      "7266.749995576748\n",
      "7251.0633228323695\n",
      "7235.491217766752\n",
      "7220.032907183193\n",
      "7204.687622476458\n",
      "7189.454599612201\n",
      "7174.3330791061435\n",
      "7159.322306003547\n",
      "7144.421529858464\n",
      "7129.630004713241\n",
      "7114.9469890778455\n",
      "7100.371745909277\n",
      "7085.9035425911225\n",
      "7071.541650913052\n",
      "7057.2853470501295\n",
      "7043.133911542665\n",
      "7029.086629275522\n",
      "7015.142789457853\n",
      "7001.301685602743\n",
      "6987.5626155067075\n",
      "6973.924881229658\n",
      "6960.387789074359\n",
      "6946.950649566326\n",
      "6933.612777433686\n",
      "6920.373491586847\n",
      "6907.232115098479\n",
      "6894.187975183342\n",
      "6881.24040317833\n",
      "6868.3887345223575\n",
      "6855.632308736373\n",
      "6842.970469403548\n",
      "6830.402564149157\n",
      "6817.927944620955\n",
      "6805.5459664691525\n",
      "6793.255989326805\n",
      "6781.057376789937\n",
      "6768.949496397916\n",
      "6756.931719613853\n",
      "6745.0034218049395\n",
      "6733.16398222282\n",
      "6721.412783984305\n",
      "6709.749214051624\n",
      "6698.1726632132395\n",
      "6686.682526064298\n",
      "6675.278200987502\n",
      "6663.959090133632\n",
      "6652.724599402387\n",
      "6641.5741384233725\n",
      "6630.507120536706\n",
      "6619.5229627741355\n",
      "6608.621085839897\n",
      "6597.800914091816\n",
      "6587.0618755224405\n",
      "6576.403401740004\n",
      "6565.8249279496795\n",
      "6555.325892934922\n",
      "6544.905739038616\n",
      "6534.563912144512\n",
      "6524.299861658595\n",
      "6514.1130404904425\n",
      "6504.002905034931\n",
      "6493.968915153628\n",
      "6484.010534156523\n",
      "6474.127228783608\n",
      "6464.318469186679\n",
      "6454.583728911094\n",
      "6444.922484877614\n",
      "6435.334217364382\n",
      "6425.818409988745\n",
      "6416.374549689388\n",
      "6407.0021267083885\n",
      "6397.700634573294\n",
      "6388.469570079409\n",
      "6379.3084332720155\n",
      "6370.216727428638\n",
      "6361.193959041441\n",
      "6352.2396377997575\n",
      "6343.35327657241\n",
      "6334.534391390459\n",
      "6325.782501429614\n",
      "6317.097128993161\n",
      "6308.477799494362\n",
      "6299.924041439608\n",
      "6291.435386411073\n",
      "6283.011369049641\n",
      "6274.6515270379905\n",
      "6266.355401083567\n",
      "6258.122534901669\n",
      "6249.952475198746\n",
      "6241.844771655417\n",
      "6233.798976909992\n",
      "6225.814646541722\n",
      "6217.891339054173\n",
      "6210.028615858833\n",
      "6202.226041258598\n",
      "6194.483182431322\n",
      "6186.799609413622\n",
      "6179.174895084475\n",
      "6171.608615149228\n",
      "6164.100348123189\n",
      "6156.649675315798\n",
      "6149.256180814449\n",
      "6141.919451468695\n",
      "6134.639076874273\n",
      "6127.414649357317\n",
      "6120.245763958598\n",
      "6113.1320184179\n",
      "6106.073013158294\n",
      "6099.068351270721\n",
      "6092.117638498294\n",
      "6085.220483221189\n",
      "6078.376496440889\n",
      "6071.585291765243\n",
      "6064.846485393038\n",
      "6058.159696098886\n",
      "6051.524545218069\n",
      "6044.940656631577\n",
      "6038.407656751151\n",
      "6031.925174504236\n",
      "6025.49284131925\n",
      "6019.11029111083\n",
      "6012.777160265001\n",
      "6006.493087624662\n",
      "6000.257714474857\n",
      "5994.070684528363\n",
      "5987.931643911253\n",
      "5981.840241148313\n",
      "5975.796127149005\n",
      "5969.798955192941\n",
      "5963.848380915842\n",
      "5957.944062295362\n",
      "5952.085659637024\n",
      "5946.272835560139\n",
      "5940.505254984036\n",
      "5934.7825851139505\n",
      "5929.104495427464\n",
      "5923.470657660552\n",
      "5917.8807457940875\n",
      "5912.3344360399515\n",
      "5906.831406827837\n",
      "5901.371338791372\n",
      "5895.953914754985\n",
      "5890.578819720452\n",
      "5885.245740853503\n",
      "5879.954367470713\n",
      "5874.704391026233\n",
      "5869.49550509873\n",
      "5864.327405378329\n",
      "5859.199789653663\n",
      "5854.112357798847\n",
      "5849.064811760677\n",
      "5844.056855545922\n",
      "5839.088195208384\n",
      "5834.158538836518\n",
      "5829.267596540453\n",
      "5824.415080439823\n",
      "5819.600704650985\n",
      "5814.824185274753\n",
      "5810.085240384027\n",
      "5805.383590011446\n",
      "5800.718956137139\n",
      "5796.091062676661\n",
      "5791.499635468687\n",
      "5786.944402263183\n",
      "5782.425092709191\n",
      "5777.9414383431185\n",
      "5773.493172576671\n",
      "5769.080030685164\n",
      "5764.701749795719\n",
      "5760.358068875659\n",
      "5756.048728720654\n",
      "5751.773471943521\n",
      "5747.532042962324\n",
      "5743.324187989262\n",
      "5739.149655018946\n",
      "5735.008193817421\n",
      "5730.899555910647\n",
      "5726.8234945733475\n",
      "5722.779764817883\n",
      "5718.768123383149\n",
      "5714.788328723551\n",
      "5710.840140997986\n",
      "5706.923322058989\n",
      "5703.037635441792\n",
      "5699.182846353641\n",
      "5695.358721662843\n",
      "5691.56502988835\n",
      "5687.80154118894\n",
      "5684.068027352647\n",
      "5680.3642617863725\n",
      "5676.690019505278\n",
      "5673.04507712254\n",
      "5669.429212838812\n",
      "5665.842206432161\n",
      "5662.283839247586\n",
      "5658.753894187104\n",
      "5655.252155699362\n",
      "5651.778409769846\n",
      "5648.332443910599\n",
      "5644.914047150496\n",
      "5641.523010025181\n",
      "5638.15912456733\n",
      "5634.822184296839\n",
      "5631.511984210957\n",
      "5628.228320774806\n",
      "5624.9709919116585\n",
      "5621.739796993379\n",
      "5618.53453683081\n",
      "5615.355013664488\n",
      "5612.201031155045\n",
      "5609.072394373949\n",
      "5605.968909794246\n",
      "5602.890385281188\n",
      "5599.836630083081\n",
      "5596.807454822117\n",
      "5593.802671485341\n",
      "5590.822093415545\n",
      "5587.865535302311\n",
      "5584.932813172977\n",
      "5582.023744383879\n",
      "5579.1381476114\n",
      "5576.27584284326\n",
      "5573.436651369764\n",
      "5570.620395775032\n",
      "5567.826899928494\n",
      "5565.055988976142\n",
      "5562.307489332157\n",
      "5559.5812286702985\n",
      "5556.877035915563\n",
      "5554.194741235689\n",
      "5551.534176032873\n",
      "5548.895172935525\n",
      "5546.277565789922\n",
      "5543.681189652056\n",
      "5541.105880779592\n",
      "5538.55147662357\n",
      "5536.017815820481\n",
      "5533.504738184262\n",
      "5531.012084698328\n",
      "5528.53969750766\n",
      "5526.087419910916\n",
      "5523.655096352617\n",
      "5521.242572415463\n",
      "5518.849694812474\n",
      "5516.476311379479\n",
      "5514.122271067311\n",
      "5511.787423934384\n",
      "5509.471621139035\n",
      "5507.174714932051\n",
      "5504.896558649333\n",
      "5502.637006704322\n",
      "5500.39591458076\n",
      "5498.173138825346\n",
      "5495.968537040417\n",
      "5493.781967876865\n",
      "5491.613291026745\n",
      "5489.462367216342\n",
      "5487.329058198911\n",
      "5485.213226747741\n",
      "5483.114736649128\n",
      "5481.033452695323\n",
      "5478.969240677745\n",
      "5476.921967379992\n",
      "5474.891500571049\n",
      "5472.8777089985015\n",
      "5470.880462381739\n",
      "5468.899631405291\n",
      "5466.935087712179\n",
      "5464.98670389716\n",
      "5463.054353500262\n",
      "5461.137911000244\n",
      "5459.237251807966\n",
      "5457.352252260098\n",
      "5455.482789612439\n",
      "5453.628742033892\n",
      "5451.789988599779\n",
      "5449.966409285715\n",
      "5448.157884961282\n",
      "5446.364297383818\n",
      "5444.58552919227\n",
      "5442.821463900948\n",
      "5441.071985893494\n",
      "5439.3369804168\n",
      "5437.616333574921\n",
      "5435.909932323127\n",
      "5434.217664461972\n",
      "5432.539418631297\n",
      "5430.875084304387\n",
      "5429.2245517821375\n",
      "5427.587712187252\n",
      "5425.9644574583845\n",
      "5424.354680344558\n",
      "5422.75827439932\n",
      "5421.175133975145\n",
      "5419.605154217829\n",
      "5418.048231060845\n",
      "5416.50426121985\n",
      "5414.973142187113\n",
      "5413.454772226067\n",
      "5411.9490503658535\n",
      "5410.455876395849\n",
      "5408.975150860408\n",
      "5407.506775053448\n",
      "5406.050651013096\n",
      "5404.606681516523\n",
      "5403.174770074595\n",
      "5401.754820926742\n",
      "5400.346739035787\n",
      "5398.950430082713\n",
      "5397.565800461676\n",
      "5396.192757274847\n",
      "5394.831208327417\n",
      "5393.481062122579\n",
      "5392.142227856564\n",
      "5390.814615413653\n",
      "5389.498135361323\n",
      "5388.192698945344\n",
      "5386.898218084963\n",
      "5385.6146053679795\n",
      "5384.341774046165\n",
      "5383.079638030298\n",
      "5381.828111885587\n",
      "5380.587110826925\n",
      "5379.356550714239\n",
      "5378.136348047887\n",
      "5376.926419964001\n",
      "5375.72668422998\n",
      "5374.5370592399395\n",
      "5373.357464010218\n",
      "5372.1878181748225\n",
      "5371.028041981093\n",
      "5369.87805628525\n",
      "5368.737782547896\n",
      "5367.60714282987\n",
      "5366.486059787728\n",
      "5365.374456669506\n",
      "5364.272257310526\n",
      "5363.179386128979\n",
      "5362.095768121899\n",
      "5361.021328860877\n",
      "5359.95599448785\n",
      "5358.899691711093\n",
      "5357.852347801045\n",
      "5356.813890586237\n",
      "5355.784248449219\n",
      "5354.763350322638\n",
      "5353.751125685109\n",
      "5352.747504557372\n",
      "5351.752417498204\n",
      "5350.76579560067\n",
      "5349.787570488161\n",
      "5348.817674310446\n",
      "5347.856039739993\n",
      "5346.902599968031\n",
      "5345.957288700884\n",
      "5345.020040156085\n",
      "5344.090789058751\n",
      "5343.169470637786\n",
      "5342.256020622274\n",
      "5341.3503752378065\n",
      "5340.452471202769\n",
      "5339.56224572485\n",
      "5338.679636497388\n",
      "5337.804581695853\n",
      "5336.937019974242\n",
      "5336.076890461683\n",
      "5335.224132758767\n",
      "5334.378686934346\n",
      "5333.540493521834\n",
      "5332.709493515938\n",
      "5331.885628369271\n",
      "5331.068839988882\n",
      "5330.25907073302\n",
      "5329.456263407729\n",
      "5328.660361263644\n",
      "5327.871307992557\n",
      "5327.089047724357\n",
      "5326.313525023634\n",
      "5325.544684886592\n",
      "5324.782472737742\n",
      "5324.026834426837\n",
      "5323.277716225698\n",
      "5322.535064825064\n",
      "5321.79882733152\n",
      "5321.068951264408\n",
      "5320.345384552741\n",
      "5319.628075532264\n",
      "5318.916972942322\n",
      "5318.2120259229405\n",
      "5317.5131840117865\n",
      "5316.82039714127\n",
      "5316.133615635677\n",
      "5315.452790208054\n",
      "5314.777871957498\n",
      "5314.108812366249\n",
      "5313.445563296744\n",
      "5312.788076988973\n",
      "5312.136306057426\n",
      "5311.490203488521\n",
      "5310.849722637678\n",
      "5310.214817226643\n",
      "5309.5854413407715\n",
      "5308.961549426227\n",
      "5308.343096287364\n",
      "5307.730037084\n",
      "5307.122327328816\n",
      "5306.519922884666\n",
      "5305.922779961982\n",
      "5305.330855116138\n",
      "5304.744105244889\n",
      "5304.162487585864\n",
      "5303.585959713888\n",
      "5303.014479538577\n",
      "5302.448005301761\n",
      "5301.886495574981\n",
      "5301.32990925705\n",
      "5300.7782055716225\n",
      "5300.231344064644\n",
      "5299.689284601988\n",
      "5299.151987367172\n",
      "5298.619412858674\n",
      "5298.091521887872\n",
      "5297.568275576478\n",
      "5297.049635354317\n",
      "5296.53556295692\n",
      "5296.026020423263\n",
      "5295.520970093505\n",
      "5295.020374606651\n",
      "5294.524196898313\n",
      "5294.032400198504\n",
      "5293.544948029348\n",
      "5293.061804202956\n",
      "5292.582932819194\n",
      "5292.108298263466\n",
      "5291.6378652045305\n",
      "5291.171598592544\n",
      "5290.709463656654\n",
      "5290.2514259031495\n",
      "5289.797451113089\n",
      "5289.347505340497\n",
      "5288.901554910003\n",
      "5288.459566415084\n",
      "5288.021506715812\n",
      "5287.587342936836\n",
      "5287.157042465514\n",
      "5286.7305729497575\n",
      "5286.307902296143\n",
      "5285.888998667933\n",
      "5285.473830483062\n",
      "5285.062366412259\n",
      "5284.654575377107\n",
      "5284.250426548089\n",
      "5283.849889342759\n",
      "5283.452933423818\n",
      "5283.059528697203\n",
      "5282.669645310292\n",
      "5282.283253650085\n",
      "5281.900324341229\n",
      "5281.520828244409\n",
      "5281.144736454281\n",
      "5280.7720202980145\n",
      "5280.402651333169\n",
      "5280.036601346157\n",
      "5279.673842350445\n",
      "5279.314346584728\n",
      "5278.958086511302\n",
      "5278.605034814269\n",
      "5278.255164397973\n",
      "5277.908448385089\n",
      "5277.564860115174\n",
      "5277.22437314283\n",
      "5276.886961236107\n",
      "5276.552598374955\n",
      "5276.221258749389\n",
      "5275.8929167581255\n",
      "5275.567547006739\n",
      "5275.245124306241\n",
      "5274.925623671366\n",
      "5274.609020319127\n",
      "5274.2952896671595\n",
      "5273.984407332247\n",
      "5273.676349128672\n",
      "5273.371091066809\n",
      "5273.068609351615\n",
      "5272.7688803809815\n",
      "5272.47188074441\n",
      "5272.177587221419\n",
      "5271.885976780163\n",
      "5271.597026575865\n",
      "5271.310713949434\n",
      "5271.027016426135\n",
      "5270.745911713877\n",
      "5270.467377702099\n",
      "5270.191392460161\n",
      "5269.917934236027\n",
      "5269.646981454934\n",
      "5269.378512717882\n",
      "5269.112506800344\n",
      "5268.848942650989\n",
      "5268.5877993901295\n",
      "5268.329056308681\n",
      "5268.072692866483\n",
      "5267.818688691291\n",
      "5267.567023577325\n",
      "5267.31767748399\n",
      "5267.070630534593\n",
      "5266.825863015053\n",
      "5266.5833553727125\n",
      "5266.343088214948\n",
      "5266.1050423080305\n",
      "5265.869198575872\n",
      "5265.635538098707\n",
      "5265.404042111957\n",
      "5265.174692005012\n",
      "5264.947469320003\n",
      "5264.722355750632\n",
      "5264.499333140986\n",
      "5264.278383484267\n",
      "5264.059488921771\n",
      "5263.842631741668\n",
      "5263.627794377812\n",
      "5263.414959408672\n",
      "5263.204109556116\n",
      "5262.995227684356\n",
      "5262.788296798843\n",
      "5262.583300045025\n",
      "5262.380220707447\n",
      "5262.179042208503\n",
      "5261.979748107446\n",
      "5261.782322099242\n",
      "5261.58674801353\n",
      "5261.393009813604\n",
      "5261.2010915953515\n",
      "5261.010977586062\n",
      "5260.8226521436645\n",
      "5260.636099755465\n",
      "5260.451305037265\n",
      "5260.268252732216\n",
      "5260.086927710014\n",
      "5259.907314965672\n",
      "5259.729399618728\n",
      "5259.553166912127\n",
      "5259.378602211336\n",
      "5259.2056910032925\n",
      "5259.0344188955305\n",
      "5258.8647716151845\n",
      "5258.696735008026\n",
      "5258.530295037578\n",
      "5258.365437784115\n",
      "5258.202149443788\n",
      "5258.040416327722\n",
      "5257.880224861054\n",
      "5257.721561582061\n",
      "5257.564413141248\n",
      "5257.408766300474\n",
      "5257.254607932053\n",
      "5257.101925017943\n",
      "5256.950704648696\n",
      "5256.800934022838\n",
      "5256.652600445844\n",
      "5256.5056913293265\n",
      "5256.360194190213\n",
      "5256.216096649916\n",
      "5256.07338643343\n",
      "5255.932051368631\n",
      "5255.792079385339\n",
      "5255.653458514535\n",
      "5255.516176887651\n",
      "5255.380222735594\n",
      "5255.245584388132\n",
      "5255.112250272981\n",
      "5254.980208915091\n",
      "5254.849448935845\n",
      "5254.719959052249\n",
      "5254.591728076272\n",
      "5254.4647449139775\n",
      "5254.338998564851\n",
      "5254.214478121015\n",
      "5254.091172766428\n",
      "5253.96907177634\n",
      "5253.848164516383\n",
      "5253.728440441816\n",
      "5253.609889096997\n",
      "5253.492500114586\n",
      "5253.376263214734\n",
      "5253.261168204474\n",
      "5253.1472049770655\n",
      "5253.03436351118\n",
      "5252.922633870394\n",
      "5252.812006202324\n",
      "5252.702470737978\n",
      "5252.594017791251\n",
      "5252.486637758062\n",
      "5252.380321115821\n",
      "5252.275058422677\n",
      "5252.170840316983\n",
      "5252.067657516481\n",
      "5251.965500817907\n",
      "5251.864361096081\n",
      "5251.764229303515\n",
      "5251.665096469633\n",
      "5251.566953700191\n",
      "5251.469792176678\n",
      "5251.373603155771\n",
      "5251.278377968512\n",
      "5251.1841080199765\n",
      "5251.090784788491\n",
      "5250.998399825084\n",
      "SVD trained finish\n"
     ]
    }
   ],
   "source": [
    "RS = RecommonderSystem()\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**这里这个打印信息太长了，可以适当减少打印的条目，显得代码整洁一些。**"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 41,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "23\n",
      "6186\n",
      "86880\n",
      "67820\n"
     ]
    }
   ],
   "source": [
    "print(np.where(RS.bu>0.001)[0].shape[0])\n",
    "print(np.where(RS.bi>0.001)[0].shape[0])\n",
    "# 训练出来的值都基本较小,我想是因为这个模型本身的分值就只有0和1,而且数据非常稀疏的缘故。我在训练的时候采用的是将BU和BI整行整列梯度训练，\n",
    "# 将P，Q整个矩阵的训练，和老师的步骤不太一样。这是我以前做梯度下降的办法，一般而言这样应该会快点收敛，准确率也不错，\n",
    "\n",
    "print(np.where(abs(RS.Q)>0.1)[0].shape[0])\n",
    "print(np.where(abs(RS.P)>0.1)[0].shape[0])\n",
    "# 这里看PQ的值的大小还是挺正常的，也不像是正则系数过大引起的。感觉这就是基于模型预测用在这里例子的结果。我看了老师的基于事件属性的预测，\n",
    "# 给出的推荐度也普遍很小。助教能解答一下这是否正常吗。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 63,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "生成训练数据...\n",
      "\n",
      "train.csv:500 (userId, eventId)=(123290209, 1887085024)\n",
      "基于用户推荐非0值 150\n",
      "基于事件推荐非0值 85\n",
      "基于模型推荐非0值 55\n",
      "基于用户属性推荐非0值 153\n",
      "基于物品属性推荐非0值 0\n",
      "train.csv:1000 (userId, eventId)=(272886293, 199858305)\n",
      "基于用户推荐非0值 319\n",
      "基于事件推荐非0值 178\n",
      "基于模型推荐非0值 122\n",
      "基于用户属性推荐非0值 329\n",
      "基于物品属性推荐非0值 0\n",
      "train.csv:1500 (userId, eventId)=(395305791, 1582270949)\n",
      "基于用户推荐非0值 463\n",
      "基于事件推荐非0值 252\n",
      "基于模型推荐非0值 166\n",
      "基于用户属性推荐非0值 479\n",
      "基于物品属性推荐非0值 0\n",
      "train.csv:2000 (userId, eventId)=(527523423, 3272728211)\n",
      "基于用户推荐非0值 609\n",
      "基于事件推荐非0值 313\n",
      "基于模型推荐非0值 219\n",
      "基于用户属性推荐非0值 619\n",
      "基于物品属性推荐非0值 0\n",
      "train.csv:2500 (userId, eventId)=(651258472, 792632006)\n",
      "基于用户推荐非0值 742\n",
      "基于事件推荐非0值 362\n",
      "基于模型推荐非0值 278\n",
      "基于用户属性推荐非0值 780\n",
      "基于物品属性推荐非0值 0\n",
      "train.csv:3000 (userId, eventId)=(811791433, 524756826)\n",
      "基于用户推荐非0值 884\n",
      "基于事件推荐非0值 422\n",
      "基于模型推荐非0值 318\n",
      "基于用户属性推荐非0值 912\n",
      "基于物品属性推荐非0值 0\n",
      "train.csv:3500 (userId, eventId)=(985547042, 1269035551)\n",
      "基于用户推荐非0值 1020\n",
      "基于事件推荐非0值 484\n",
      "基于模型推荐非0值 365\n",
      "基于用户属性推荐非0值 1064\n",
      "基于物品属性推荐非0值 0\n",
      "train.csv:4000 (userId, eventId)=(1107615001, 173949238)\n",
      "基于用户推荐非0值 1173\n",
      "基于事件推荐非0值 554\n",
      "基于模型推荐非0值 412\n",
      "基于用户属性推荐非0值 1201\n",
      "基于物品属性推荐非0值 0\n",
      "train.csv:4500 (userId, eventId)=(1236336671, 3849306291)\n",
      "基于用户推荐非0值 1306\n",
      "基于事件推荐非0值 608\n",
      "基于模型推荐非0值 459\n",
      "基于用户属性推荐非0值 1341\n",
      "基于物品属性推荐非0值 0\n",
      "train.csv:5000 (userId, eventId)=(1414301782, 2652356640)\n",
      "基于用户推荐非0值 1440\n",
      "基于事件推荐非0值 684\n",
      "基于模型推荐非0值 514\n",
      "基于用户属性推荐非0值 1489\n",
      "基于物品属性推荐非0值 0\n",
      "train.csv:5500 (userId, eventId)=(1595465532, 955398943)\n",
      "基于用户推荐非0值 1583\n",
      "基于事件推荐非0值 751\n",
      "基于模型推荐非0值 568\n",
      "基于用户属性推荐非0值 1659\n",
      "基于物品属性推荐非0值 0\n",
      "train.csv:6000 (userId, eventId)=(1747091728, 2131379889)\n",
      "基于用户推荐非0值 1727\n",
      "基于事件推荐非0值 810\n",
      "基于模型推荐非0值 621\n",
      "基于用户属性推荐非0值 1811\n",
      "基于物品属性推荐非0值 0\n",
      "train.csv:6500 (userId, eventId)=(1914182220, 955398943)\n",
      "基于用户推荐非0值 1864\n",
      "基于事件推荐非0值 882\n",
      "基于模型推荐非0值 687\n",
      "基于用户属性推荐非0值 1970\n",
      "基于物品属性推荐非0值 0\n",
      "train.csv:7000 (userId, eventId)=(2071842684, 1076364848)\n",
      "基于用户推荐非0值 2016\n",
      "基于事件推荐非0值 951\n",
      "基于模型推荐非0值 729\n",
      "基于用户属性推荐非0值 2107\n",
      "基于物品属性推荐非0值 0\n",
      "train.csv:7500 (userId, eventId)=(2217853337, 3051438735)\n",
      "基于用户推荐非0值 2160\n",
      "基于事件推荐非0值 1027\n",
      "基于模型推荐非0值 782\n",
      "基于用户属性推荐非0值 2254\n",
      "基于物品属性推荐非0值 0\n",
      "train.csv:8000 (userId, eventId)=(2338481531, 2525447278)\n",
      "基于用户推荐非0值 2299\n",
      "基于事件推荐非0值 1107\n",
      "基于模型推荐非0值 843\n",
      "基于用户属性推荐非0值 2418\n",
      "基于物品属性推荐非0值 0\n",
      "train.csv:8500 (userId, eventId)=(2489551967, 520657921)\n",
      "基于用户推荐非0值 2430\n",
      "基于事件推荐非0值 1178\n",
      "基于模型推荐非0值 889\n",
      "基于用户属性推荐非0值 2552\n",
      "基于物品属性推荐非0值 0\n",
      "train.csv:9000 (userId, eventId)=(2650493630, 87962584)\n",
      "基于用户推荐非0值 2585\n",
      "基于事件推荐非0值 1247\n",
      "基于模型推荐非0值 932\n",
      "基于用户属性推荐非0值 2702\n",
      "基于物品属性推荐非0值 0\n",
      "train.csv:9500 (userId, eventId)=(2791418962, 4223848259)\n",
      "基于用户推荐非0值 2749\n",
      "基于事件推荐非0值 1328\n",
      "基于模型推荐非0值 974\n",
      "基于用户属性推荐非0值 2846\n",
      "基于物品属性推荐非0值 0\n",
      "train.csv:10000 (userId, eventId)=(2903662804, 2791462807)\n",
      "基于用户推荐非0值 2874\n",
      "基于事件推荐非0值 1379\n",
      "基于模型推荐非0值 1015\n",
      "基于用户属性推荐非0值 2966\n",
      "基于物品属性推荐非0值 0\n",
      "train.csv:10500 (userId, eventId)=(3036141956, 3929507420)\n",
      "基于用户推荐非0值 3006\n",
      "基于事件推荐非0值 1422\n",
      "基于模型推荐非0值 1054\n",
      "基于用户属性推荐非0值 3070\n",
      "基于物品属性推荐非0值 0\n",
      "train.csv:11000 (userId, eventId)=(3176074542, 3459485614)\n",
      "基于用户推荐非0值 3137\n",
      "基于事件推荐非0值 1476\n",
      "基于模型推荐非0值 1098\n",
      "基于用户属性推荐非0值 3186\n",
      "基于物品属性推荐非0值 0\n",
      "train.csv:11500 (userId, eventId)=(3285425249, 2271782630)\n",
      "基于用户推荐非0值 3287\n",
      "基于事件推荐非0值 1557\n",
      "基于模型推荐非0值 1164\n",
      "基于用户属性推荐非0值 3326\n",
      "基于物品属性推荐非0值 0\n",
      "train.csv:12000 (userId, eventId)=(3410667855, 1063772489)\n",
      "基于用户推荐非0值 3433\n",
      "基于事件推荐非0值 1621\n",
      "基于模型推荐非0值 1212\n",
      "基于用户属性推荐非0值 3471\n",
      "基于物品属性推荐非0值 0\n",
      "train.csv:12500 (userId, eventId)=(3531604778, 2584839423)\n",
      "基于用户推荐非0值 3585\n",
      "基于事件推荐非0值 1686\n",
      "基于模型推荐非0值 1263\n",
      "基于用户属性推荐非0值 3602\n",
      "基于物品属性推荐非0值 0\n",
      "train.csv:13000 (userId, eventId)=(3686871863, 53495098)\n",
      "基于用户推荐非0值 3721\n",
      "基于事件推荐非0值 1752\n",
      "基于模型推荐非0值 1310\n",
      "基于用户属性推荐非0值 3768\n",
      "基于物品属性推荐非0值 0\n",
      "train.csv:13500 (userId, eventId)=(3833637800, 2415873572)\n",
      "基于用户推荐非0值 3868\n",
      "基于事件推荐非0值 1822\n",
      "基于模型推荐非0值 1354\n",
      "基于用户属性推荐非0值 3906\n",
      "基于物品属性推荐非0值 0\n",
      "train.csv:14000 (userId, eventId)=(3944021305, 2096772901)\n",
      "基于用户推荐非0值 4025\n",
      "基于事件推荐非0值 1895\n",
      "基于模型推荐非0值 1418\n",
      "基于用户属性推荐非0值 4046\n",
      "基于物品属性推荐非0值 0\n",
      "train.csv:14500 (userId, eventId)=(4075466480, 3567240505)\n",
      "基于用户推荐非0值 4163\n",
      "基于事件推荐非0值 1960\n",
      "基于模型推荐非0值 1468\n",
      "基于用户属性推荐非0值 4167\n",
      "基于物品属性推荐非0值 0\n",
      "train.csv:15000 (userId, eventId)=(4197193550, 1628057176)\n",
      "基于用户推荐非0值 4343\n",
      "基于事件推荐非0值 2042\n",
      "基于模型推荐非0值 1514\n",
      "基于用户属性推荐非0值 4312\n",
      "基于物品属性推荐非0值 0\n",
      "生成预测数据...\n",
      "\n",
      "test.csv:500 (userId, eventId)=(182290053, 2529072432)\n",
      "基于用户推荐非0值 0\n",
      "基于事件推荐非0值 38\n",
      "基于模型推荐非0值 45\n",
      "基于用户属性推荐非0值 0\n",
      "基于物品属性推荐非0值 0\n",
      "test.csv:1000 (userId, eventId)=(433510318, 4244463632)\n",
      "基于用户推荐非0值 0\n",
      "基于事件推荐非0值 65\n",
      "基于模型推荐非0值 84\n",
      "基于用户属性推荐非0值 0\n",
      "基于物品属性推荐非0值 0\n",
      "test.csv:1500 (userId, eventId)=(632808865, 2845303452)\n",
      "基于用户推荐非0值 0\n",
      "基于事件推荐非0值 110\n",
      "基于模型推荐非0值 132\n",
      "基于用户属性推荐非0值 0\n",
      "基于物品属性推荐非0值 0\n",
      "test.csv:2000 (userId, eventId)=(813611885, 2036538169)\n",
      "基于用户推荐非0值 0\n",
      "基于事件推荐非0值 133\n",
      "基于模型推荐非0值 160\n",
      "基于用户属性推荐非0值 0\n",
      "基于物品属性推荐非0值 0\n",
      "test.csv:2500 (userId, eventId)=(1010701404, 303459881)\n",
      "基于用户推荐非0值 0\n",
      "基于事件推荐非0值 157\n",
      "基于模型推荐非0值 200\n",
      "基于用户属性推荐非0值 0\n",
      "基于物品属性推荐非0值 0\n",
      "test.csv:3000 (userId, eventId)=(1210932037, 2529072432)\n",
      "基于用户推荐非0值 0\n",
      "基于事件推荐非0值 187\n",
      "基于模型推荐非0值 239\n",
      "基于用户属性推荐非0值 0\n",
      "基于物品属性推荐非0值 0\n",
      "test.csv:3500 (userId, eventId)=(1452921099, 2705317682)\n",
      "基于用户推荐非0值 0\n",
      "基于事件推荐非0值 215\n",
      "基于模型推荐非0值 290\n",
      "基于用户属性推荐非0值 0\n",
      "基于物品属性推荐非0值 0\n",
      "test.csv:4000 (userId, eventId)=(1623287180, 1626678328)\n",
      "基于用户推荐非0值 0\n",
      "基于事件推荐非0值 241\n",
      "基于模型推荐非0值 323\n",
      "基于用户属性推荐非0值 0\n",
      "基于物品属性推荐非0值 0\n",
      "test.csv:4500 (userId, eventId)=(1855201342, 2603032829)\n",
      "基于用户推荐非0值 0\n",
      "基于事件推荐非0值 270\n",
      "基于模型推荐非0值 362\n",
      "基于用户属性推荐非0值 0\n",
      "基于物品属性推荐非0值 0\n",
      "test.csv:5000 (userId, eventId)=(2083900381, 2529072432)\n",
      "基于用户推荐非0值 0\n",
      "基于事件推荐非0值 302\n",
      "基于模型推荐非0值 402\n",
      "基于用户属性推荐非0值 0\n",
      "基于物品属性推荐非0值 0\n",
      "test.csv:5500 (userId, eventId)=(2318415276, 2509151803)\n",
      "基于用户推荐非0值 0\n",
      "基于事件推荐非0值 342\n",
      "基于模型推荐非0值 461\n",
      "基于用户属性推荐非0值 0\n",
      "基于物品属性推荐非0值 0\n",
      "test.csv:6000 (userId, eventId)=(2528161539, 4025975316)\n",
      "基于用户推荐非0值 0\n",
      "基于事件推荐非0值 371\n",
      "基于模型推荐非0值 494\n",
      "基于用户属性推荐非0值 0\n",
      "基于物品属性推荐非0值 0\n",
      "test.csv:6500 (userId, eventId)=(2749110768, 4244406355)\n",
      "基于用户推荐非0值 0\n",
      "基于事件推荐非0值 409\n",
      "基于模型推荐非0值 532\n",
      "基于用户属性推荐非0值 0\n",
      "基于物品属性推荐非0值 0\n",
      "test.csv:7000 (userId, eventId)=(2927772127, 1532377761)\n",
      "基于用户推荐非0值 0\n",
      "基于事件推荐非0值 440\n",
      "基于模型推荐非0值 570\n",
      "基于用户属性推荐非0值 0\n",
      "基于物品属性推荐非0值 0\n",
      "test.csv:7500 (userId, eventId)=(3199685636, 1776393554)\n",
      "基于用户推荐非0值 0\n",
      "基于事件推荐非0值 487\n",
      "基于模型推荐非0值 615\n",
      "基于用户属性推荐非0值 0\n",
      "基于物品属性推荐非0值 0\n",
      "test.csv:8000 (userId, eventId)=(3393388475, 680270887)\n",
      "基于用户推荐非0值 0\n",
      "基于事件推荐非0值 513\n",
      "基于模型推荐非0值 651\n",
      "基于用户属性推荐非0值 0\n",
      "基于物品属性推荐非0值 0\n",
      "test.csv:8500 (userId, eventId)=(3601169721, 154434302)\n",
      "基于用户推荐非0值 0\n",
      "基于事件推荐非0值 545\n",
      "基于模型推荐非0值 686\n",
      "基于用户属性推荐非0值 0\n",
      "基于物品属性推荐非0值 0\n",
      "test.csv:9000 (userId, eventId)=(3828963415, 3067222491)\n",
      "基于用户推荐非0值 0\n",
      "基于事件推荐非0值 569\n",
      "基于模型推荐非0值 714\n",
      "基于用户属性推荐非0值 0\n",
      "基于物品属性推荐非0值 0\n",
      "test.csv:9500 (userId, eventId)=(4018723397, 2522610844)\n",
      "基于用户推荐非0值 0\n",
      "基于事件推荐非0值 604\n",
      "基于模型推荐非0值 761\n",
      "基于用户属性推荐非0值 0\n",
      "基于物品属性推荐非0值 0\n",
      "test.csv:10000 (userId, eventId)=(4180064266, 2658555390)\n",
      "基于用户推荐非0值 0\n",
      "基于事件推荐非0值 642\n",
      "基于模型推荐非0值 804\n",
      "基于用户属性推荐非0值 0\n",
      "基于物品属性推荐非0值 0\n"
     ]
    }
   ],
   "source": [
    "\n",
    "print \"生成训练数据...\\n\"\n",
    "generateRSData(RS,train=True,  header=True)\n",
    "\n",
    "print \"生成预测数据...\\n\"\n",
    "generateRSData(RS, train=False, header=True)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "在训练集中，SVD模型通过的预测值普遍就很小,但是我觉得也许只需要根据整体大小算出来的计算一个合理的阈值选择推荐也是一种方法。上面其他模型判断非0的阈值是0.2,而SVD模型协同预测是0.005，普遍都很小。直观感觉通过相似的用户和事件进行推荐的确是比较直接的方法，相比起SVD分解再重组得出推荐度好像也的确简单很多，尤其是数据极度稀疏的情况下，这种推荐方法基本过滤了绝大部分的0值数据进行的计算，使整个过程更为简单直接，那给出比较高的分数似乎也是合理的。而SVD分解似乎并不能做到，因为在计算的过程中，没有直接过滤掉0值数据的影响，其中的步骤需要考虑到一个用户对所有事件的评分和一个事件的所有评分，并且即使是0值，似乎也会对计算产生影响，因此只能给出非常保守的推荐度，不知道理解得对不对。整体而言这所有的推荐度矩阵都还是相当稀疏的。而根据老师的代码计算出来的基于物品属性的推荐度普遍很低很低，我看过矩阵里面的值也都非常的小，相乘起来就更小了，似乎通过这个方法给不出很有用的信息。\n",
    "\n",
    "而在TEST集的结果可以看出来，基于用户属性，用户关联，事件属性的推荐模型基本给不出任何有效的推荐值.\n",
    "根据下面对用户参加事件数目的分析，矩阵非常稀疏。而且所有事件之间没有采用关联，比如说‘复仇者联盟’和‘蝙蝠侠’都是一类电影这样,训练集并没有这样做。那么除非TEST里面的用户和事件组合在TRAIN里面是出现过的，否则根据用户之间的相似性基本不可能给出任何的推荐度。简单的说，比如认为A，B，C用户相似，那么如果TEST里面要预测A用户对X事件的推荐度，就必须根据B，C用户对X事件的评分，那么除非在训练集中出现过BC对X事件的评分，否则评分就没法评，但能想到这种情况的概率基本很低很低。\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 61,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "(array([  11,   32,   35,   42,   64,   79,   91,  110,  117,  119,  140,\n",
      "        151,  173,  175,  202,  208,  214,  257,  262,  265,  266,  267,\n",
      "        289,  320,  327,  336,  380,  381,  391,  416,  417,  422,  423,\n",
      "        437,  448,  460,  472,  474,  500,  554,  559,  562,  584,  592,\n",
      "        594,  605,  617,  628,  630,  646,  654,  662,  664,  706,  733,\n",
      "        766,  781,  782,  789,  820,  827,  829,  835,  844,  853,  857,\n",
      "        873,  892,  893,  926,  938,  958,  973,  998, 1007, 1052, 1053,\n",
      "       1066, 1071, 1121, 1147, 1150, 1191, 1206, 1212, 1215, 1231, 1245,\n",
      "       1259, 1268, 1289, 1298, 1306, 1322, 1325, 1354, 1362, 1395, 1400,\n",
      "       1418, 1422, 1442, 1487, 1488, 1528, 1535, 1561, 1577, 1581, 1590,\n",
      "       1594, 1601, 1610, 1639, 1645, 1653, 1672, 1676, 1703, 1728, 1735,\n",
      "       1746, 1752, 1816, 1835, 1838, 1849, 1867, 1884, 1891, 1905, 1912,\n",
      "       1921, 1927, 1936, 1941, 1942, 1947, 1960, 1994, 1997, 1999, 2011,\n",
      "       2030, 2035, 2041, 2045, 2057, 2072, 2097, 2130, 2152, 2154, 2176,\n",
      "       2180, 2183, 2195, 2231, 2234, 2246, 2251, 2256, 2269, 2274, 2277,\n",
      "       2282, 2318, 2321, 2328, 2339, 2345, 2363, 2376, 2386, 2400, 2410,\n",
      "       2425, 2427, 2443, 2447, 2483, 2485, 2491, 2495, 2496, 2500, 2541,\n",
      "       2548, 2549, 2563, 2595, 2597, 2598, 2621, 2631, 2635, 2648, 2661,\n",
      "       2673, 2694, 2695, 2698, 2703, 2751, 2753, 2780, 2784, 2790, 2808,\n",
      "       2813, 2815, 2826, 2859, 2862, 2878, 2891, 2898, 2905, 2906, 2911,\n",
      "       2925, 2927, 2932, 2935, 2961, 2982, 2983, 2995, 2996, 3002, 3014,\n",
      "       3016, 3028, 3046, 3050, 3070, 3074, 3079, 3087, 3089, 3122, 3176,\n",
      "       3179, 3185, 3200, 3202, 3207, 3216, 3226, 3238, 3240, 3256, 3260,\n",
      "       3274, 3290, 3291, 3293, 3314, 3320, 3327, 3363, 3367, 3373, 3379,\n",
      "       3384]),)\n",
      "(array([   88,   184,   667,   689,   796,   976,  1092,  1656,  1706,\n",
      "        1729,  2047,  2106,  2178,  2271,  2388,  2410,  2574,  2691,\n",
      "        2730,  2891,  3503,  3523,  3770,  3821,  3908,  3917,  4003,\n",
      "        4061,  4070,  4089,  4094,  4122,  4254,  4287,  4359,  4433,\n",
      "        4667,  4769,  4778,  4923,  5030,  5081,  5155,  5308,  5400,\n",
      "        5558,  5856,  5863,  5883,  6125,  6319,  6811,  6978,  7150,\n",
      "        7158,  7162,  7169,  7253,  7535,  7554,  7843,  7857,  7981,\n",
      "        8101,  8201,  8216,  8282,  8666,  8753,  9012,  9020,  9208,\n",
      "        9244,  9262,  9315,  9471,  9513,  9751,  9878, 10183, 10218,\n",
      "       10245, 10445, 10464, 10539, 10575, 10682, 11325, 11342, 12084,\n",
      "       12449, 12467, 12708, 12747, 12822, 12880, 12908, 12931, 12978,\n",
      "       13001, 13047, 13111, 13309, 13378]),)\n"
     ]
    }
   ],
   "source": [
    "print(np.where (RS.R.sum(axis=1)>3))\n",
    "print(np.where (RS.R.sum(axis=0)>3))\n",
    "#观察TRAIN 的数据和R矩阵的值的情况。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "anaconda-cloud": {},
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.4"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
